package upm.pb4agent.team3;

import jade.content.Concept;
import jade.content.ContentElement;
import jade.content.lang.Codec;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.basic.Action;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.util.leap.ArrayList;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import upm.pb4agent.ontology.AssignBoat;
import upm.pb4agent.ontology.DenyRow;
import upm.pb4agent.ontology.Dock;
import upm.pb4agent.ontology.DockDesignation;
import upm.pb4agent.ontology.EnteringDock;
import upm.pb4agent.ontology.LeavingDock;
import upm.pb4agent.ontology.PB4AgentOntology;
import upm.pb4agent.ontology.RaceFinished;
import upm.pb4agent.ontology.RealRow;
import upm.pb4agent.ontology.Registration;
import upm.pb4agent.ontology.Row;
import upm.pb4agent.ontology.Seat;

/**
 * This agent has the following functionality: 
 * <ul>
 * <li> 
 * <li> 
 * </ul>
 * @author Team3, UPM
 */
public class Watcher extends Agent {
	private static final long serialVersionUID = 1532765201921703535L;

	private Codec codec = new SLCodec();
	private Ontology ontology = PB4AgentOntology.getInstance();
	private AID agRefereeAid = null;
	private Map<String, AID> mapTeampBoatAID = new HashMap<String, AID>();
	
	public boolean isRaceStarted=false;
	public boolean isRaceFinishedByTeam=false;
	
	
	private HashMap<AID, RowerBean> rowerBeanHashMap = new HashMap<AID, RowerBean>();
	
	private int rowSeconds;
	
	private double circuitLength;
	private double boardingExtension;
	
	private double frontOarXCoef;
	private double backOarXCoef;
	private double frontOarYCoef;
	private double backOarYCoef;
	
	private double impulseWeak;
	private double impulseMedium;
	private double impulseStrong;
		
	private double rower1Strength;	
	private double rower1Resistance;
	private double rower1Agility;
	
	private double rower2Strength;	
	private double rower2Resistance;
	private double rower2Agility;
	
	private double rower3Strength;	
	private double rower3Resistance;
	private double rower3Agility;
	
	private double rower4Strength;
	private double rower4Resistance;	
	private double rower4Agility;
	
	int x=0;
	int y=0;
		
	protected void setup(){		
		System.out.println(getLocalName() + ": enters the system");
		
		getContentManager().registerLanguage(codec);
		getContentManager().registerOntology(ontology);
		
		MyAgent.registerAgentInDF(this, getLocalName());
		agRefereeAid = MyAgent.searchAgentInDF(this,Constant.SD_REFEREE);
		
		addBehaviour(new SubscriptionInitiatorToReferee(this));
		addBehaviour(new ReceiveRegistrationFormFromRegistrationDesk(this));
		
		readPhysicalProperties();
		setCircuit();circuitToString();
		
		addBehaviour(new ProcessRowInformationForRowers(this));
	}


	class ReceiveRegistrationFormFromRegistrationDesk extends SimpleBehaviour {

		private static final long serialVersionUID = 5084745544985575209L;

		boolean end = false;
		
		public ReceiveRegistrationFormFromRegistrationDesk(Agent agent) {
			super(agent);
		}

		public void action() {
				
			ACLMessage receiveRegInfMsg = receive(MessageTemplate.and(
														MessageTemplate.and(
																			  MessageTemplate.and(
																								    MessageTemplate.MatchLanguage(codec.getName())
																								   ,MessageTemplate.MatchOntology(ontology.getName())
																				 	 			  )
																		     ,MessageTemplate.MatchPerformative(ACLMessage.INFORM)
																		   )
																		 ,MessageTemplate.MatchProtocol("MakeBoat")
																		 )
												
													);															

			if(receiveRegInfMsg != null){
				if(receiveRegInfMsg.getProtocol().toString().equals("MakeBoat")) {
					try{
						ContentElement contentElement = getContentManager().extractContent(receiveRegInfMsg);						
						if(contentElement instanceof Action){
							Action action = (Action) contentElement;
							Concept concept = action.getAction();
							if(concept instanceof Registration){
								Registration registration = (Registration) concept;
								//System.out.println(getLocalName() + ": INFORM: WatchBoat received <-- "+ Constant.SD_REGISTRATION_DESK);
									
								/**
								 * 2)Watcher then creates the boat and then inform the rowers of 
								 * the team about the boat (Action: AssignBoat(boatAID).
								 */
								if(registration.getRegistrationForm() != null){
									String teamID = registration.getRegistrationForm().getTeamID().getValue();
									
									AID boatAID = createBoatXForTeamXAgent(Constant.NAME_BOAT_X + "_for_" + teamID);
									//Creates the description for the type of agent to be searched						  							  				
									//It finds agents of the required type																	
									
									AssignBoat assignedBoat = new AssignBoat();
									upm.pb4agent.ontology.Boat boat = new upm.pb4agent.ontology.Boat();
									boat.setSeats(getListSeats());
									boat.setID(boatAID);
									assignedBoat.setBoat(boat);	
									
									mapTeampBoatAID.put(teamID,boatAID);
									
									for(int k=0; k<registration.getRegistrationForm().getDockDesignation().size();k++){										
										ACLMessage msgAssignBoat = new ACLMessage(ACLMessage.INFORM);										
										msgAssignBoat.setLanguage(codec.getName());
										msgAssignBoat.setOntology(ontology.getName());  								  						
										msgAssignBoat.setProtocol("AssignBoat"); 
										
										DockDesignation dockDesignation = (DockDesignation) registration.getRegistrationForm().getDockDesignation().get(k);											
										AID agRowerAid = dockDesignation.getRowerID();
										msgAssignBoat.addReceiver(agRowerAid);											
										Action asignedBoatgAction = new Action(agRowerAid,assignedBoat);											
																				
										
										getContentManager().fillContent(msgAssignBoat, asignedBoatgAction);
										send(msgAssignBoat);
										System.out.println(getLocalName() + ", 'AssignBoat' --> " + agRowerAid.getLocalName());
									}				
								}								
							}
						}
					}catch(Exception e){
						System.out.println(getLocalName() + ", error: " + e.toString());
					}
									
				}else if (receiveRegInfMsg.getProtocol().toString().equals("RegistrationClosed")) {
					//System.out.println(getLocalName() + ": RegistrationClosed: no more make boats ");
					end = true;
				}
			}else{				
				//System.out.println(getLocalName() + ": Waiting for RegistrationToWatcher <-- "+ Constant.SD_REGISTRATION_DESK);
				end = false;
				block();				
			}
		}
		
		public boolean done() {
			return end;
		}
	}
	
	
	public AID createBoatXForTeamXAgent(String boatXForTeamX) {
		try {
			AgentContainer agentContainer = getContainerController();

			AgentController agentController = agentContainer.createNewAgent(  boatXForTeamX
																			, Constant.CLASS_BOAT
																			, new String[] { "3"});
			agentController.start();
			
			AID boatAID = new AID(boatXForTeamX, AID.ISLOCALNAME);
			
//boatHashMap.put(boatAID, new Coordinate());
			return boatAID;
		} catch (Exception e) {
			System.out.println(getLocalName() + ", error: " + e.toString());
			return null;
		}
	}
	
	public jade.util.leap.List getListSeats() {
		try {
			Seat seat1 = new Seat();
			seat1.setSeatID(Constant.NAME_SEAT_1);
			Seat seat2 = new Seat();
			seat2.setSeatID(Constant.NAME_SEAT_2);
			Seat seat3 = new Seat();
			seat3.setSeatID(Constant.NAME_SEAT_3);
			Seat seat4 = new Seat();
			seat4.setSeatID(Constant.NAME_SEAT_4);
			Seat seat5 = new Seat();
			seat5.setSeatID(Constant.NAME_SEAT_5);
			Seat seat6 = new Seat();
			seat6.setSeatID(Constant.NAME_SEAT_6);
			
			jade.util.leap.List listSeats = new ArrayList();
			listSeats.add(seat1);
			listSeats.add(seat2);
			listSeats.add(seat3);
			listSeats.add(seat4);
			listSeats.add(seat5);
			listSeats.add(seat6);
			
			return listSeats;
		} catch (Exception e) {
			System.out.println(getLocalName() + ", error: " + e.toString());
			return null;
		}
	}
	
	
	class ProcessRowInformationForRowers extends SimpleBehaviour{
		private static final long serialVersionUID = 3844912585144138107L;
		
		public ProcessRowInformationForRowers(Agent agent) {
			super(agent);
		}

		public void action(){
			try{			
				ACLMessage msg = receive(MessageTemplate.MatchProtocol("Row"));
				if(msg == null){
					block();
				}else{
					ACLMessage reply = msg.createReply();
					ContentElement contentElement = getContentManager().extractContent(msg);
						
					if(contentElement instanceof Action) {
						Action action = (Action) contentElement;
						Concept concept = action.getAction();
						if(concept instanceof Row) {							
							analizeRowRequestForRower(msg,(Row)concept, msg.getSender());
						}else{
							ACLMessage replyMsg = new ACLMessage(ACLMessage.NOT_UNDERSTOOD);
							replyMsg.addReceiver(msg.getSender());	
							replyMsg.setLanguage(codec.getName());
							replyMsg.setOntology(ontology.getName());		    		    
					    	//replyMsg.setProtocol("Row");
					    	send(replyMsg);
					    	System.out.println(getLocalName() + " Row:NotUnderstood --> " + msg.getSender().getLocalName());	
						}
					}else{
						reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
						send(reply);
					}
				}
			}catch(Exception e){
				System.out.println(getLocalName() + ", error: " + e.toString());
			}
		}

		public boolean done() {
			return isRaceFinishedByTeam;
		}
	}		
	
	public int getSeconds(long dateL){
		Date date = new Date(dateL);
		return date.getSeconds();
	}

	public long getMilliSeconds(int seconds){
		Date date = new Date();
		date.setSeconds(seconds);
		long ss = date.getTime();
		return ss;
	}
	
	private void analizeRowRequestForRower(ACLMessage receive, Row row, AID rowerAID){
		try{
		   long currentTimeRow = System.currentTimeMillis();
		   
		   RowerBean rowerBean;	
		   boolean isNewRowerBean = false;
		   
  
		   if( rowerBeanHashMap.containsKey( receive.getSender()) ){
			   rowerBean = rowerBeanHashMap.get(receive.getSender());
		   }else{
			   isNewRowerBean = true;			   
			   rowerBean = new RowerBean();
			   rowerBean.rowerAID = receive.getSender();			   
			   rowerBean.rowerNum = parseNumRower(rowerBean.rowerAID);
			   
			   rowerBean.strengthValue = parseStrength(rowerBean.rowerNum); 
			   rowerBean.resistance = parseResistance(rowerBean.rowerNum); 
			   rowerBean.agility = parseAgility(rowerBean.rowerNum);
			   			  
			   //time_row(0) = row_seconds - agility
			   float seconds = this.rowSeconds - (float)rowerBean.agility;			   		  
			   if(seconds <= 0) seconds = 1;
			   rowerBean.timeRow = seconds;
			   
			   rowerBean.impulse = parseImpulse(row.getStrength());
			   
			   rowerBean.realRow = new RealRow();
			   rowerBean.realRow.setX(0);
			   rowerBean.realRow.setY(0);
		   }
		   
		   rowerBean.row = row;	
		   long diff = (currentTimeRow - rowerBean.lastTimeRowed);
		   
		  /* System.out.println(" ");
		   System.out.println(" rowerBean <");		
		   //System.out.println(" rowerBean " + rowerBean.toString());
		   System.out.println(" rowerBean.timeRow " + rowerBean.timeRow);	
		   System.out.println(" diff " + diff);	
		   System.out.println(" rowerBean >");	*/	   		 
		   
		   if((float)(currentTimeRow - rowerBean.lastTimeRowed) >= rowerBean.timeRow){
		   /*if(   (Float)diff >= rowerBean.timeRow
			  || rowerBean.lastTimeRowed == 0){//allow to row*/
			   			
			   RealRow realRow = new RealRow();	
			   x = x + getX(rowerBean);
			   y = y + getY(rowerBean);			   
			   realRow.setX(x);
			   realRow.setY(y);
			   
			   /*realRow.setX(rowerBean.realRow.getX() + getX(rowerBean));			   
			   realRow.setY(rowerBean.realRow.getY() + getY(rowerBean));*/
			   
			   realRow.setOarID(row.getOarID());
			   rowerBean.realRow = realRow;
			   			   
			   rowerBean.tiredness = getTiredness(rowerBean);
			   //time_row(t) = time_row(t-1) + tiredness(t)			   
			   //rowerBean.timeRow = rowerBean.timeRow + (int) rowerBean.tiredness);
			   rowerBean.timeRow = rowerBean.timeRow + (float) rowerBean.tiredness;
			   rowerBean.lastTimeRowed = currentTimeRow;
			   
			   System.out.println(getLocalName() + ": " + receive.getSender().getLocalName() 
					   + ": Oar: " + row.getOarID() 
					   + ": Rowed 'x=" + realRow.getX() + ", y=" + realRow.getY() 
					   + "' " + row.getBoat().getID().getLocalName());
			   			   
			   ACLMessage reply = new ACLMessage(ACLMessage.INFORM);
			   reply.addReceiver(receive.getSender());
			   //reply.addReceiver(rowerBean.row.getBoat().getID());
			   reply.setLanguage(codec.getName());
			   reply.setOntology(ontology.getName());		    	
			   reply.setProtocol("RealRow");		    			    	
			   Action actionRealRow = new Action(receive.getSender(),realRow);
			   getContentManager().fillContent(reply, actionRealRow);				
			   send(reply);
			   
			   
			   //
			   RealRow realRowBoat = realRow;			   
			   if(y<0)realRowBoat.setY(25*Constant.TEAM_NUMBER);
			   if(x<0)realRowBoat.setX(0);
			   
			   ACLMessage msgBoat = new ACLMessage(ACLMessage.INFORM);
			   msgBoat.addReceiver(rowerBean.row.getBoat().getID());
			   msgBoat.setLanguage(codec.getName());
			   msgBoat.setOntology(ontology.getName());		    	
			   msgBoat.setProtocol("RealRow");		    			    	
			   Action actionRealRowBoat = new Action(rowerBean.row.getBoat().getID(),realRowBoat);
			   getContentManager().fillContent(msgBoat, actionRealRowBoat);				
			   send(msgBoat);
			   			   
			   checkBoardingLeavingDock(rowerBean.row.getBoat(),realRow.getX(), realRow.getY());
			   
		   }else{//deny it
			   DenyRow denyRow = new DenyRow();
			   denyRow.setOarID(row.getOarID());
			   
			   Action actionDenyRow = new Action(receive.getSender(),denyRow);
			   
			   ACLMessage reply = new ACLMessage(ACLMessage.REFUSE);
			   reply.addReceiver(receive.getSender());
			   reply.setLanguage(codec.getName());
			   reply.setOntology(ontology.getName());		    	
			   reply.setProtocol("DenyRow");
			   getContentManager().fillContent(reply, actionDenyRow);
			   send(reply);
			   //System.out.println(getLocalName() + " Row:DenyRow --> " + receive.getSender().getLocalName());	
		   }
		   		   
		   if(isNewRowerBean){
			   rowerBeanHashMap.put(receive.getSender(), rowerBean);
		   }
		   		   
		}catch(Exception e) {
			System.out.println(getLocalName() + ".row(), error: " + e.toString());
		}
	}
	
	
	double circuitPartLength = 0;
	double dockA_y_e = 0;
	double dockA_y_l = 0;
		
	double dockB_y_e = 0;
	double dockB_y_l = 0;
	
	double dockC_y_e = 0;
	double dockC_y_l = 0;
	
	double dockD_y_e = 0;
	double dockD_y_l = 0;
	
	public void setCircuit(){
		circuitPartLength = circuitLength / Constant.MAX_NUMBER_OF_DOCKS;
		
		/*
		//dockA_y_e = 0;
		dockA_y_l = boardingExtension;
		
		dockB_y_e = circuitPartLength;
		dockB_y_l = circuitPartLength + boardingExtension;
		
		dockC_y_e = 2*circuitPartLength;
		dockC_y_l = 2*circuitPartLength + boardingExtension;
		
		dockD_y_e = 3*circuitPartLength;
		dockD_y_l = 3*circuitPartLength + boardingExtension;*/
		
		
		int circuitPartLengthInt = (int)circuitPartLength;
		
		dockA_y_l = boardingExtension;
		
		dockB_y_e = circuitPartLengthInt;
		dockB_y_l = circuitPartLengthInt + boardingExtension;
		
		dockC_y_e = 2*circuitPartLengthInt;
		dockC_y_l = 2*circuitPartLengthInt + boardingExtension;
		
		dockD_y_e = 3*circuitPartLengthInt;
		dockD_y_l = 3*circuitPartLengthInt + boardingExtension;
	}
	
	public void circuitToString(){		
		StringBuffer stb = new StringBuffer();
		stb.append("circuitLength: " + circuitLength);
		stb.append(": circuitPartLength: " + circuitPartLength);
		stb.append(" :dockA: <" + dockA_y_e + "," + dockA_y_l + ">");
		stb.append(" :dockB: <" + dockB_y_e + "," + dockB_y_l + ">");
		stb.append(" :dockC: <" + dockC_y_e + "," + dockC_y_l + ">");
		stb.append(" :dockD: <" + dockD_y_e + "," + dockD_y_l + ">");
		stb.append(" :finishLine: <"+ circuitLength + ">");
		System.out.println(stb.toString());
	}
	
	
	/*double finish_y = circuitPartLength;*/	
	private void checkBoardingLeavingDock(upm.pb4agent.ontology.Boat boat, int x, int y){
		try{			
			if (y == boardingExtension){
				msgLeavingDockToReferee(boat,Constant.NAME_DOCK_A);
				//System.out.println("++++++++++++++++++++++++++++++++++Leaving dock A " + y);
			}
			
			if (y == dockB_y_e){
				//System.out.println("::::::::::::::::::::::::::::::::::Entering dock B " + y);
				msgEnteringDockToReferee(boat,Constant.NAME_DOCK_B, y);
			}else if (y == dockB_y_l){
				msgLeavingDockToReferee(boat,Constant.NAME_DOCK_B);
				//System.out.println("++++++++++++++++++++++++++++++++++Leaving dock B " + y);
			}
			
			if (y == dockC_y_e){
				//System.out.println("::::::::::::::::::::::::::::::::::Entering dock C " + y);
				msgEnteringDockToReferee(boat,Constant.NAME_DOCK_C, y);
			}else if (y == dockC_y_l){
				msgLeavingDockToReferee(boat,Constant.NAME_DOCK_C);
				//System.out.println("++++++++++++++++++++++++++++++++++Leaving dock C " + y);
			}
			
			if (y == dockD_y_e){
				//System.out.println("::::::::::::::::::::::::::::::::::Entering dock D " + y);
				msgEnteringDockToReferee(boat,Constant.NAME_DOCK_D, y);
			}else if (y == dockD_y_l){
				msgLeavingDockToReferee(boat,Constant.NAME_DOCK_D);
				//System.out.println("++++++++++++++++++++++++++++++++++Leaving dock D " + y);
			}
			
			if (y >= circuitLength){
				isRaceFinishedByTeam = true;
				sendRaceFinishedToReferee(boat,y);
				System.out.println("**********************************LLego a la meta final " + y);
			}
			
		}catch(Exception e) {
			System.out.println(getLocalName() + ".checkBoardingLeavingDock(), error: " + e.toString());
		}
}
	
	private void msgEnteringDockToReferee(upm.pb4agent.ontology.Boat boat, String dockName, int position){
	    try{
			if(agRefereeAid == null){
				agRefereeAid = MyAgent.searchAgentInDF(this,Constant.SD_REFEREE);
			}
			
			Dock dock = new Dock();
		    dock.setName(dockName);
	
		    EnteringDock enteringDock = new EnteringDock();
		    enteringDock.setBoatAID(boat.getID());
		    enteringDock.setDock(dock);
		    enteringDock.setPosition(position);
		    enteringDock.setTimeStamp(Long.toString(System.currentTimeMillis()));		   
		    
		    Action actionEnteringDock = new Action(agRefereeAid,enteringDock);
		    
		    ACLMessage mensaje = new ACLMessage(ACLMessage.INFORM);	   
		    mensaje.setLanguage(codec.getName());
		    mensaje.setOntology(ontology.getName());
		    mensaje.setProtocol("EnteringDock");
		    mensaje.addReceiver(agRefereeAid);		    
			getContentManager().fillContent(mensaje, actionEnteringDock);
			send(mensaje);
			//System.out.println(getLocalName() + " EnteringDock --> " + agRefereeAid.getLocalName());
	    }catch(Exception e) {
			System.out.println(getLocalName() + ".msgEnteringDockToReferee(), error: " + e.toString());
		}
	  }

	private void msgLeavingDockToReferee(upm.pb4agent.ontology.Boat boat, String dockName){
		try{
			if(agRefereeAid == null){
				agRefereeAid = MyAgent.searchAgentInDF(this,Constant.SD_REFEREE);
			}
			
			Dock dock = new Dock();
		    dock.setName(dockName);
	
		    LeavingDock leavingDock = new LeavingDock();
		    leavingDock.setBoatAID(boat.getID());
		    leavingDock.setDock(dock);
		    
		    Action actionLeavingDock = new Action(agRefereeAid,leavingDock);
		    
		    ACLMessage mensaje = new ACLMessage(ACLMessage.INFORM);	   
		    mensaje.setLanguage(codec.getName());
		    mensaje.setOntology(ontology.getName());
		    mensaje.setProtocol("LeavingDock");
		    mensaje.addReceiver(agRefereeAid);
			getContentManager().fillContent(mensaje, actionLeavingDock);
			send(mensaje);
			//System.out.println(getLocalName() + " LeavingDock --> " + agRefereeAid.getLocalName());
		}catch(Exception e) {
			System.out.println(getLocalName() + ".msgLeavingDockToReferee(), error: " + e.toString());
		}
	}

	private void sendRaceFinishedToReferee(upm.pb4agent.ontology.Boat boat, int position){
	    try{
			RaceFinished raceFinished = new RaceFinished();
		    raceFinished.setBoatAID(boat.getID());
		    raceFinished.setPosition(1);//position
		    raceFinished.setTimeStamp(Long.toString(System.currentTimeMillis()));
		    
		    Action actionRaceFinished = new Action(agRefereeAid,raceFinished);
	
		    ACLMessage mensaje = new ACLMessage(ACLMessage.INFORM);	   
		    mensaje.setLanguage(codec.getName());
		    mensaje.setOntology(ontology.getName());
		    mensaje.setProtocol("RaceFinished");
		    mensaje.addReceiver(agRefereeAid);
			getContentManager().fillContent(mensaje, actionRaceFinished);
			send(mensaje);
			//System.out.println(getLocalName() + " RaceFinished --> " + agRefereeAid.getLocalName());
	    }catch(Exception e) {
			System.out.println(getLocalName() + ".msgRaceFinishedToReferee(), error: " + e.toString());
		}
	}
	
	
	private void readPhysicalProperties(){
		ReadConfiguration.getInstance(0);		
		//
		String propTmp = ReadConfiguration.getValue("circuit_length");
		if(propTmp != null){
			this.circuitLength = Double.parseDouble(propTmp);					
		}
		propTmp = ReadConfiguration.getValue("boarding_extension");
		if(propTmp != null){
			this.boardingExtension = Double.parseDouble(propTmp);					
		}
		
		//
		propTmp = ReadConfiguration.getValue("row_seconds");
		if(propTmp != null){
			this.rowSeconds = Integer.parseInt(propTmp);					
		}
		
		//
		propTmp = ReadConfiguration.getValue("front_oar_x_coef");
		if(propTmp != null){
			this.frontOarXCoef = Double.parseDouble(propTmp);					
		}
		
		propTmp = ReadConfiguration.getValue("back_oar_x_coef");
		if(propTmp != null){
			this.backOarXCoef = Double.parseDouble(propTmp);	
		}
		
		propTmp = ReadConfiguration.getValue("front_oar_y_coef");
		if(propTmp != null){
			this.frontOarYCoef = Double.parseDouble(propTmp);					
		}
		
		propTmp = ReadConfiguration.getValue("back_oar_y_coef");
		if(propTmp != null){
			this.backOarYCoef = Double.parseDouble(propTmp);	
		}
		
		//
		propTmp = ReadConfiguration.getValue("impulse_weak");
		if(propTmp != null){
			this.impulseWeak = Double.parseDouble(propTmp);					
		}
		
		propTmp = ReadConfiguration.getValue("impulse_medium");
		if(propTmp != null){
			this.impulseMedium = Double.parseDouble(propTmp);	
		}
		
		
		propTmp = ReadConfiguration.getValue("impulse_strong");
		if(propTmp != null){
			this.impulseStrong = Double.parseDouble(propTmp);	
		}
		
		//
		propTmp = ReadConfiguration.getValue("rower1_strength");
		if(propTmp != null){
			this.rower1Strength = Double.parseDouble(propTmp);	
		}
		propTmp = ReadConfiguration.getValue("rower1_resistance");
		if(propTmp != null){
			this.rower1Resistance = Double.parseDouble(propTmp);	
		}		
		propTmp = ReadConfiguration.getValue("rower1_agility");
		if(propTmp != null){
			this.rower1Agility = Double.parseDouble(propTmp);	
		}
		
		
		propTmp = ReadConfiguration.getValue("rower2_strength");
		if(propTmp != null){
			this.rower2Strength = Double.parseDouble(propTmp);	
		}
		propTmp = ReadConfiguration.getValue("rower2_resistance");
		if(propTmp != null){
			this.rower2Resistance = Double.parseDouble(propTmp);	
		}		
		propTmp = ReadConfiguration.getValue("rower2_agility");
		if(propTmp != null){
			this.rower2Agility = Double.parseDouble(propTmp);	
		}
		
		propTmp = ReadConfiguration.getValue("rower3_strength");
		if(propTmp != null){
			this.rower3Strength = Double.parseDouble(propTmp);	
		}
		propTmp = ReadConfiguration.getValue("rower3_resistance");
		if(propTmp != null){
			this.rower3Resistance = Double.parseDouble(propTmp);	
		}		
		propTmp = ReadConfiguration.getValue("rower3_agility");
		if(propTmp != null){
			this.rower3Agility = Double.parseDouble(propTmp);	
		}
		
		
		propTmp = ReadConfiguration.getValue("rower4_strength");
		if(propTmp != null){
			this.rower4Strength = Double.parseDouble(propTmp);	
		}
		propTmp = ReadConfiguration.getValue("rower4_resistance");
		if(propTmp != null){
			this.rower4Resistance = Double.parseDouble(propTmp);	
		}		
		propTmp = ReadConfiguration.getValue("rower4_agility");
		if(propTmp != null){
			this.rower4Agility = Double.parseDouble(propTmp);	
		}
	}
	
	private double parseImpulse(int impulseEnum){
		
		if (impulseEnum == MyEnumImpulse.WEAK.getImpulse()){
			return this.impulseWeak;
		}else if (impulseEnum == MyEnumImpulse.MEDIUM.getImpulse()){
			return this.impulseMedium;
		}else if (impulseEnum == MyEnumImpulse.STRONG.getImpulse()){
			return this.impulseStrong;
		}

		return 0;
	}
	
	private double getTiredness(RowerBean rowerBean){
		//tiredness(0) = 0
		//tiredness(t) = tiredness(t-1) + impulse(t) * (1-resistance)
		//tiredness(t <= 1
		
		double tiredness = rowerBean.tiredness + rowerBean.impulse * (1 - rowerBean.resistance);
		if(tiredness > 1){
			tiredness = 1;
		}
		/*System.out.println("");
		System.out.println("impulse:   " + impulse);
		System.out.println("resistance:   " + resistance);
		System.out.println("impulse * (1 - resistance):   " + impulse * (1 - resistance));
		System.out.println("previousTiredness: " + previousTiredness);
		System.out.println("tiredness: " + tiredness);
		System.out.println("");*/
		return tiredness;
	}
	
	private double parseOarCoefX(String oarName){
		double oarXCoef = 0;
		if(	   oarName.equalsIgnoreCase(Constant.NAME_OAR_1)
				|| oarName.equalsIgnoreCase(Constant.NAME_OAR_2) ){
			oarXCoef = frontOarXCoef;
				
		}else if(    oarName.equalsIgnoreCase(Constant.NAME_OAR_3)
				  || oarName.equalsIgnoreCase(Constant.NAME_OAR_4) ){
			oarXCoef = backOarXCoef;
		}
		
		
		if(    oarName.equalsIgnoreCase(Constant.NAME_OAR_1)
			|| oarName.equalsIgnoreCase(Constant.NAME_OAR_3) ){
			oarXCoef = oarXCoef *-1;
		}
	
		return oarXCoef;
	}
	
	private double parseOarCoefY(String oarName){
		double oarYCoef = 0;		
		if(	   oarName.equalsIgnoreCase(Constant.NAME_OAR_1)
			|| oarName.equalsIgnoreCase(Constant.NAME_OAR_2) ){
			oarYCoef = frontOarYCoef;
		}else if(    oarName.equalsIgnoreCase(Constant.NAME_OAR_3)
				  || oarName.equalsIgnoreCase(Constant.NAME_OAR_4) ){
			oarYCoef = backOarYCoef;
		}
		return oarYCoef;
	}
	
	
	private int parseNumRower(AID rowerAID){
		 int rowerNum = Integer.parseInt(rowerAID.getLocalName().substring(rowerAID.getLocalName().length() - 1), rowerAID.getLocalName().length());
		 return rowerNum;
	}
	
	private double parseStrength(int numRower){
		switch(numRower) {
			case 1:
				return this.rower1Strength;
			case 2:
				return this.rower2Strength;
			case 3:
				return this.rower3Strength;
			case 4:
				return this.rower4Strength;
			default:
				return 0;
		}
	}
	
	private double parseResistance(int numRower){
		switch(numRower) {
			case 1:
				return this.rower1Resistance;
			case 2:
				return this.rower2Resistance;
			case 3:
				return this.rower3Resistance;
			case 4:
				return this.rower4Resistance;
			default:
				return 0;
		}		
	}
	
	private double parseAgility(int numRower){
		switch(numRower) {
			case 1:
				return this.rower1Agility;
			case 2:
				return this.rower2Agility;
			case 3:
				return this.rower3Agility;
			case 4:
				return this.rower4Agility;
			default:
				return 0;
		}
	}

	
	private int getX(RowerBean rowerBean){
		//x = impulse * (strength - tiredness) * oar_x_coef		
		double oarXCoef = parseOarCoefX(rowerBean.row.getOarID());	
		double xDouble = rowerBean.impulse * (rowerBean.strengthValue - rowerBean.tiredness) * oarXCoef;
		
		int x = (int) Math.ceil(xDouble);
		if(x == 0) x = 1;
		if(oarXCoef<0) x=x*-1;
		
		/*System.out.println("x: " + x);
		
		System.out.println("");
		System.out.println("impulse:   " + parseImpulse(rowerBean.row.getStrength()));
		System.out.println("rowerBean.strengthValue:   " + String.valueOf(rowerBean.strengthValue));
		System.out.println("rowerBean.tiredness:   " + rowerBean.tiredness);
		System.out.println("oarXCoef: " + oarXCoef);
		System.out.println("x: " + x);
		System.out.println("");*/
		
		return x;
	}
	
	private int getY(RowerBean rowerBean){
		//y = impulse * (strength - tiredness) * oar_y_coef 
		double oarYCoef = parseOarCoefY(rowerBean.row.getOarID());
		double yDouble = rowerBean.impulse * (rowerBean.strengthValue - rowerBean.tiredness) * oarYCoef;
		int y = (int) Math.ceil(yDouble);
		
		if(rowerBean.row.getDirection() == MyEnumDirection.BACKWARD.getDirection()){
			y = y*(-1);
		}
		
		/*System.out.println("");
		System.out.println("impulse:   " + parseImpulse(rowerBean.row.getStrength()));
		System.out.println("rowerBean.strengthValue:   " + String.valueOf(rowerBean.strengthValue));
		System.out.println("rowerBean.tiredness:   " + rowerBean.tiredness);
		System.out.println("oarXCoef: " + oarYCoef);
		System.out.println("y: " + y);
		System.out.println("");*/
		return y;
	}
}